import React from 'react';
import { message, Select } from 'antd';
import moment from 'moment';
import * as R from 'ramda';
import {
  DATE_HMS,
  DATE_noHMS,
  endFormat,
  startFormat,
  successCode,
} from '../support/constant/common';
import { stringify } from 'qs';
import { generateFingerprint } from '@/utils/fingerprint';
const { Option } = Select;

/**
 * description: 这是一个通用的工具类，作用简化开发。
 * rules: {
 *     1：你必须保证你创建的方法是common类型的，而不是只是为了某一特定的功能。
 *     2：当你试图创建新的方法的时候，必须加上注释，说明方法的作用。
 *     3：你应该保证你所创建的方法是简洁，健壮，有思考的。（拒绝任意一行的废弃代码）
 *     4. 思考使用ramda库中的方法和es6中 array，string对象的方法
 *     5. 方法参数尽量要有默认值
 * }
 *
 * -----------------------------------------------------   非常华丽的分割线   -----------------------------------------------------
 */

// * -> Boolean
export const isEmptyOrNil = R.anyPass([R.isEmpty, R.isNil]);

// * -> Boolean
export const isNotEmptyAndNil = R.complement(isEmptyOrNil);

// {} -> Boolean
export const isSuccess = R.compose(R.includes(R.__, successCode), R.prop('statusCode'));

// [a] -> [String] -> [o]
// o = <Option>
export const transferOption = (arrayData = [], keyValue = ['value', 'label']) =>
  R.map(
    item => (
      <Option key={item[keyValue[0]]} value={item[keyValue[0]]}>
        {item[keyValue[1]]}
      </Option>
    ),
    arrayData,
  );

export const doCallBack = R.curry((callBackFun, prompt, { statusCode, statusMessage }) => {
  const successAction = () => {
    message.success(prompt);
    callBackFun();
  };
  const errorAction = () => message.error(statusMessage);
  R.ifElse(R.includes(R.__, successCode), successAction, errorAction)(statusCode);
});

//数据字典前缀
const head = 'managementplat-';

// {k:v} -> k -> [b]
export const getDicByCode = R.curry((data, code) => {
  code = head + code;
  return R.propOr([], code, data);
});

// Ord b => (a → b) → a → a → Number
// {k:v} -> k -> [b]
const sortBySort = R.ascend(R.prop('sort'));
export const getDicByCodeSort = R.curry((data, code) => {
  return R.sort(sortBySort)(getDicByCode(data, code));
});

// {k:v} -> k -> String -> String
export const getDicByKey = R.curry((data, code, key) => {
  code = head + code;
  return R.ifElse(
    R.anyPass([isEmptyOrNil, R.compose(isEmptyOrNil, R.prop(code))]),
    R.always(key),
    R.compose(R.propOr(key, 'value'), R.find(R.propEq('key', key)), R.propOr([], code)),
  )(data);
});

export const getDataByCode = R.curry((data, code, key) =>
  R.ifElse(
    R.anyPass([isEmptyOrNil, R.compose(isEmptyOrNil, R.prop(code))]),
    R.always(key),
    R.compose(R.propOr(key, 'name'), R.find(R.propEq('code', key)), R.propOr([], code)),
  )(data),
);

// * -> String
export const getToken = () =>
  localStorage.getItem('REMEMBER')
    ? localStorage.getItem('token')
    : sessionStorage.getItem('token');


export const getFingerprint = async () => {
  let fingerprint = sessionStorage.getItem('fingerprint');
  if(!fingerprint) {
    fingerprint = await generateFingerprint();
    sessionStorage.setItem('fingerprint', fingerprint)
  }
  return fingerprint
}
// {a} -> {a}
export function omitEmptyAndNil(data) {
  return R.compose(
    R.map(R.when(R.compose(R.equals('Object'), R.type), omitEmptyAndNil)),
    R.pickBy(isNotEmptyAndNil),
  )(data);
}

// {o:n} -> {k:v} -> {n:v}
export const renameKeys = R.curry((keysMap, obj) =>
  R.reduce((acc, key) => R.assoc(keysMap[key] || key, obj[key], acc), {}, R.keys(obj)),
);

// [a] -> {o:n} -> [a]
export const renameKeysArray = R.curry((keysMap, arrayData) =>
  R.map(renameKeys(keysMap), arrayData),
);

// {} -> {} | false
export const paginationProps = R.ifElse(
  isEmptyOrNil,
  R.F,
  R.mergeRight({
    showSizeChanger: true,
    showQuickJumper: true,
    showTotal: total => <span>共&nbsp;{total}&nbsp;条</span>,
  }),
);

// [a] -> a
export const randomItem = R.converge(R.nth, [
  R.compose(Math.round, R.converge(R.multiply, [Math.random, R.compose(R.dec, R.length)])),
  R.identity,
]);

// [a] -> [b]  -> [a]
export const sortByGivenList = R.curry((givenList, sourceData) =>
  R.sort((a, b) => R.converge(R.subtract, [R.indexOf(a.key), R.indexOf(b.key)])(givenList))(
    sourceData,
  ),
);

// [String] -> [a] -> [a]
export const accessAuthorityButton = R.curry((targetButton, btns) =>
  R.compose(
    sortByGivenList(targetButton),
    R.filter(t => R.includes(t.key, targetButton)),
  )(btns),
);

// [a] -> [String] -> String -> {a}
export const filterListToObject = (listData, pickKey, key = 'key') =>
  R.pipe(
    R.filter(t => R.includes(t[key], pickKey)),
    R.reduce((targetObject, current) => ({ ...targetObject, ...current }), {}),
  )(listData);

// [k,v] -> String -> [{k:v}] -> v
export const getValueFromList = R.curry(([keyProp, valueProp], key, list) =>
  R.pipe(
    R.find(R.propEq(keyProp, key)),
    R.defaultTo({}),
    R.view(R.lensProp(valueProp)),
    R.defaultTo(''),
  )(list),
);

// String -> Moment -> String
export const dateTimeFormat = R.curry((dateFormat, date) => moment(date).format(dateFormat));
// String -> String
export const dateFormatHMS = dateTimeFormat(DATE_HMS);
// String -> String
export const dateFormatNoHMS = dateTimeFormat(DATE_noHMS);
// String -> String
export const startDayFormat = start => moment(start).startOf('d').format(startFormat);
// String -> String
export const endDayFormat = end => moment(end).startOf('d').format(endFormat);

export const separateParamAndBody = params => {
  const keywordsList = ['pageNo', 'pageSize'];
  const keys = Object.keys(params);
  let pagination = {};
  let data = {};
  keys.forEach(k => {
    if (keywordsList.indexOf(k) !== -1) {
      pagination[k] = params[k];
    } else {
      data[k] = params[k];
    }
  });
  return {
    pagination,
    data,
  };
};

export const isJson = str => {
  if (str) {
    try {
      let obj = JSON.parse(str);
      return !!(typeof obj === 'object' && obj !== null);
    } catch (error) {
      return false;
    }
  }
  return false;
};

export const getOptAuthHeaders = () => {
  let fingerprint = sessionStorage.getItem('fingerprint');
  return {
    'x-dfiov-fingerprint': fingerprint || 'undefined'
  }
}